// Diagnostics.cs
//

using System;
using System.Collections;
using System.Html;
using System.Runtime.CompilerServices;
using System.Serialization;
using ThemeChain;
using jQueryApi;

namespace Nsb.Classes
{
    [IgnoreNamespace] // So that non-script# scripts can call Inform.log()
    public static class Inform
    {
        public static bool Tracing;
        public static bool PassExceptions;
        public static bool LogActions;
        public static bool Debugging;
        private static int _mark;

        /// <summary>
        /// Logs the specified MSG to the console.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        [AlternateSignature]
        public static extern void Debug(string msg);

        [AlternateSignature]
        public static extern void Debug(string msg, object v1);

        [AlternateSignature]
        public static extern void Debug(string msg, object v1, object v2);

        [AlternateSignature]
        public static extern void Debug(string msg, object v1, object v2, object v3);

        public static void Debug(string msg, object v1, object v2, object v3, object v4)
        {
#if DEBUG
            //if (Debugging)
            Script.Literal("if (window.console) console.warn({0})", String.Format("D" + (new Date()).GetTime() + ": " + msg, v1, v2, v3, v4));
#endif
        }

        /// <summary>
        /// Logs the specified MSG to the console.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        [AlternateSignature]
        public static extern void Log(string msg);

        [AlternateSignature]
        public static extern void Log(string msg, object v1);

        [AlternateSignature]
        public static extern void Log(string msg, object v1, object v2);

        [AlternateSignature]
        public static extern void Log(string msg, object v1, object v2, object v3);

        public static void Log(string msg, object v1, object v2, object v3, object v4)
        {
#if DEBUG
            Script.Literal("if (window.console) console.log({0})", String.Format(msg, v1, v2, v3, v4));
#endif
        }


        [AlternateSignature]
        public static extern void Trace(string msg);

        [AlternateSignature]
        public static extern void Trace(string msg, object v1);

        [AlternateSignature]
        public static extern void Trace(string msg, object v1, object v2);

        [AlternateSignature]
        public static extern void Trace(string msg, object v1, object v2, object v3);

        public static void Trace(string msg, object v1, object v2, object v3, object v4)
        {
#if DEBUG
            if (Tracing)
                Script.Literal("if (window.console) console.log({0})", String.Format("Trace: " + msg, v1, v2, v3, v4));
#endif
        }

        /// <summary>
        /// Logs the specified MSG to the console as a warning.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        [AlternateSignature]
        public static extern void Warn(string msg);

        [AlternateSignature]
        public static extern void Warn(string msg, object v1);

        [AlternateSignature]
        public static extern void Warn(string msg, object v1, object v2);

        [AlternateSignature]
        public static extern void Warn(string msg, object v1, object v2, object v3);

        public static void Warn(string msg, object v1, object v2, object v3, object v4)
        {
#if DEBUG
            Script.Literal("if (window.console) console.warn({0})", String.Format(msg, v1, v2, v3, v4));
#endif
        }

        [AlternateSignature]
        public static extern void Error(string msg);

        [AlternateSignature]
        public static extern void Error(string msg, object v1);

        [AlternateSignature]
        public static extern void Error(string msg, object v1, object v2);

        [AlternateSignature]
        public static extern void Error(string msg, object v1, object v2, object v3);

        public static void Error(string msg, object v1, object v2, object v3, object v4)
        {
            msg = String.Format(msg, v1, v2, v3, v4);
            if (msg.IndexOf(Exceptions.IsLoggedTxt) == -1)
            {
                Script.Literal("if (window.console) console.error({0})", msg);
                Exceptions.SaveLog(ThemeBase.ErrorLogName, msg);
            }
        }

        [AlternateSignature]
        public static extern void RawError(string msg);

        [AlternateSignature]
        public static extern void RawError(string msg, object v1);

        [AlternateSignature]
        public static extern void RawError(string msg, object v1, object v2);

        [AlternateSignature]
        public static extern void RawError(string msg, object v1, object v2, object v3);

        public static void RawError(string msg, object v1, object v2, object v3, object v4)
        {
            msg = String.Format(msg, v1, v2, v3, v4);
            Script.Literal("if (window.console) console.error({0})", msg);
        }

        [AlternateSignature]
        public static extern void Dump(object item);

        public static void Dump(object item, string name)
        {
            Log("Dump of object \"{0}\"", Script.IsValue(name) ? name : "Type=" + item.GetType());

            string s = Json.Stringify(item, delegate(string n, object o) { return o; }, 4);
            Script.Literal("if (window.console) console.log({0})", s);
        }


        /// <summary>
        /// Logs the function name.
        /// </summary>
        /// <param name="args">Script.Literal("arguments")</param>
        public static void LogFn(object args)
        {
            string n = (string) Script.Literal("{0}.callee.name", args);
            if (!String.IsNullOrEmpty(n))
                Log("Doing {0}", n);
        }

        [AlternateSignature]
        public static extern void Event(object args);

        /// <summary>
        /// Logs the function name to event logs
        /// </summary>
        /// <param name="args">Script.Literal("arguments")</param>
        /// <param name="msg">optional message</param>
        public static void Event(object args, string msg)
        {
            string n;
            if (args is string)
                n = (string)args;
            else
                n = (string)Script.Literal("{0}.callee.name", args);
            msg = String.IsNullOrEmpty(msg) ? String.Format("{0}", n ?? "anonymous") : String.Format("{0} : {1}", n ?? "anonymous", msg);
            Debug("(Event) " + msg);
            Exceptions.SaveLog(ThemeBase.EventLogName, msg);
        }

        public static void MarkSt()
        {
            _mark = (new Date()).GetTime();
        }

        public static void Mark()
        {
            int m = (new Date()).GetTime();
            Log("Mark {0}", (double) (m - _mark)/1000);
            _mark = m;
        }
    }
}